﻿using FullSearch.Common;
using Lucene.Net.Documents;
using Lucene.Net.Facet;
using Lucene.Net.Spatial.Prefix;
using Lucene.Net.Spatial.Prefix.Tree;
using Lucene.Net.Util;
using Spatial4n.Context;
using System;
using System.Linq;

namespace FullSearch
{
    internal static class DocumentExtension
    {
        public static void Add(this Document doc, DocFieldEntity entity, params DocFieldBoost[] boostList)
        {
            Type t;
            object val;
            if (entity.ValueType == "String")
            {
                t = typeof(string);
                val = entity.Value;
            }
            else if (entity.ValueType == "Double")
            {
                t = typeof(double);
                val = Convert.ToDouble(entity.Value);
            }
            else if (entity.ValueType == "Decimal")
            {
                t = typeof(decimal);
                val = Convert.ToDecimal(entity.Value);
            }
            else if (entity.ValueType == "Single")
            {
                t = typeof(float);
                val = Convert.ToSingle(entity.Value);
            }
            else if (entity.ValueType == "DateTime")
            {
                t = typeof(DateTime);
                val = Convert.ToDateTime(entity.Value);
            }
            else if (entity.ValueType == "Int64")
            {
                t = typeof(long);
                val = Convert.ToInt64(entity.Value);
            }
            else
            {
                t = typeof(int);
                val = Convert.ToInt32(entity.Value);
            }

            doc.Add(entity.Name, val, t, entity.Stored, entity.Analyzer, entity.DocValues, entity.Facet, entity.Geo, boostList);
        }

        public static void Add(this Document doc, string name, object value, Type valueType, bool stored, bool analyzer, bool docValues, bool facet, bool geo, params DocFieldBoost[] boostList)
        {
            var fstored = Field.Store.YES;
            if (!stored)
            {
                fstored = Field.Store.NO;
            }
            Field field;

            if (valueType == typeof(string))
            {
                string val = (string)value;
                if (val == null)
                {
                    val = "";
                }

                if (geo)
                {
                    field = new StoredField(name, val);
                    var ctx = SpatialContext.Geo;
                    var grid = new GeohashPrefixTree(ctx, 11);
                    var strategy = new RecursivePrefixTreeStrategy(grid, name);
                    var arr = val.Split(' ');
                    var x = Convert.ToDouble(arr[0]);
                    var y = Convert.ToDouble(arr[1]);
                    var point = ctx.MakePoint(x, y);//这里的x,y即经纬度，x为Longitude(经度),y为Latitude(纬度)
                    var geoFields = strategy.CreateIndexableFields(point);
                    foreach (var item in geoFields)
                    {
                        doc.Add(item);
                    }
                }
                else if (analyzer)
                {
                    field = new TextField(name, val, fstored);
                }
                else
                {
                    field = new StringField(name, val, fstored);
                    if (docValues)
                    {
                        doc.Add(new SortedDocValuesField(name, new BytesRef(val)));
                    }
                }
            }
            else if (valueType == typeof(double) || valueType == typeof(decimal))
            {
                var val = (double)value;
                field = new DoubleField(name, val, fstored);
                if (docValues)
                {
                    doc.Add(new DoubleDocValuesField(name, val));
                }
            }
            else if (valueType == typeof(float))
            {
                var val = (float)value;
                field = new SingleField(name, val, fstored);
                if (docValues)
                {
                    doc.Add(new SingleDocValuesField(name, val));
                }
            }
            else if (valueType == typeof(DateTime))
            {
                var val = DateTools.Round((DateTime)value, DateResolution.MILLISECOND).Ticks;
                field = new Int64Field(name, val, fstored);
                if (docValues)
                {
                    doc.Add(new NumericDocValuesField(name, val));
                }
            }
            else
            {
                if (valueType == typeof(long))
                {
                    field = new Int64Field(name, (long)value, fstored);
                }
                else
                {
                    field = new Int32Field(name, Convert.ToInt32(value), fstored);
                }

                if (docValues)
                {
                    doc.Add(new NumericDocValuesField(name, Convert.ToInt64(value)));
                }
            }
            if (boostList.Length > 0)
            {
                var boost = boostList.FirstOrDefault(f => f.Name == name);
                if (boost != null)
                {
                    field.Boost = boost.Boost;
                }
            }
            doc.Add(field);
            if (facet)
            {
                doc.Add(new FacetField(name, value.ToString()));
            }
        }

    }
}
